from celery import current_app
from flask import Blueprint, jsonify, send_file, request, abort, make_response, redirect, url_for
from datetime import date, datetime
import io
import pandas as pd
import zipfile
from .models import ScheduleResult, Elderdemand, TimeSlot, DicNursingAction, Attendantskills, CaregiverSchedule, ShiftAssignment, db
from .scheduler import Plan
from .three_shift import ThreeShiftScheduler
from config_params import params
from sqlalchemy import func
from .redis_utils import get_redis_connection
from .redis_utils import get_update_time

main = Blueprint('main', __name__)

@main.route('/')
def index():
    return "Welcome to the Nursing Schedule App!"

@main.route('/check_update', methods=['GET'])
def check_update():
    redis_conn = get_redis_connection()
    if redis_conn:
        update_value = redis_conn.get(current_app.config['REDIS_UPDATE_KEY'])
        return jsonify({"update": update_value})
    else:
        return jsonify({"error": "无法连接到Redis"}), 500

@main.route('/last_update_time', methods=['GET'])
def get_last_update_time():
    last_update_time = get_update_time()
    if last_update_time:
        return jsonify({"last_update_time": last_update_time})
    else:
        return jsonify({"error": "无法获取最后更新时间"}), 404

@main.route('/generate_and_save_schedule', methods=['GET', 'POST'])
def generate_and_save_schedule():
    plan = Plan(params)
    plan.run()  # 运行排班算法并保存结果

    if request.method == 'POST':
        return jsonify({"message": "Schedules generated and saved successfully", "date": datetime.now().isoformat()})
    else:
        return redirect(url_for('main.view_schedule'))

@main.route('/caregiver_schedule/<string:caregiver_id>', methods=['GET'])
def get_caregiver_schedule(caregiver_id):
    schedule_date_str = request.args.get('date', date.today().isoformat())
    schedule_date = datetime.strptime(schedule_date_str, "%Y-%m-%d").date()

    schedules = CaregiverSchedule.query.filter(
        CaregiverSchedule.caregiver_id == caregiver_id,
        func.date(CaregiverSchedule.schedule_date) == schedule_date
    ).order_by(CaregiverSchedule.time_slot).all()

    return jsonify([{
        'time_slot': schedule.time_slot,
        'is_available': schedule.is_available
    } for schedule in schedules])

@main.route('/update_caregiver_availability', methods=['POST'])
def update_caregiver_availability():
    data = request.json
    caregiver_id = data.get('caregiver_id')
    schedule_date_str = data.get('date')
    time_slot = data.get('time_slot')
    is_available = data.get('is_available')

    if not all([caregiver_id, schedule_date_str, time_slot is not None, is_available is not None]):
        return jsonify({'error': 'Missing required data'}), 400

    schedule_date = datetime.strptime(schedule_date_str, "%Y-%m-%d").date()

    schedule = CaregiverSchedule.query.filter_by(
        caregiver_id=caregiver_id,
        schedule_date=schedule_date,
        time_slot=time_slot
    ).first()

    if schedule:
        schedule.is_available = is_available
    else:
        new_schedule = CaregiverSchedule(
            caregiver_id=caregiver_id,
            schedule_date=schedule_date,
            time_slot=time_slot,
            is_available=is_available
        )
        db.session.add(new_schedule)

    try:
        db.session.commit()
        return jsonify({'message': 'Caregiver availability updated successfully'}), 200
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500

@main.route('/view_schedule', methods=['GET'])
def view_schedule():
    elder = request.args.get('elder')
    schedule_date_str = request.args.get('date', date.today().isoformat())
    schedule_date = datetime.strptime(schedule_date_str, "%Y-%m-%d").date()

    def process_time_slot(ts):
        return {
            'id': ts.id,
            'elder': ts.elder,
            'time_slot': ts.time_slot,
            'activity': ts.activity,
            'activity_id': ts.activity_id,
            'caregiver': 'lack' if ts.caregiver_id == '-1' else ts.caregiver,
            'caregiver_id': ts.caregiver_id,
            'schedule_date': ts.schedule_date.isoformat()
        }

    try:
        if elder:
            schedule_result = ScheduleResult.query.filter(
                ScheduleResult.elder == elder,
                db.func.date(ScheduleResult.schedule_date) == schedule_date
            ).first()
            if schedule_result:
                time_slots = TimeSlot.query.filter_by(schedule_result_id=schedule_result.id).order_by(
                    TimeSlot.time_order).all()
                return jsonify({
                    'elder': elder,
                    'schedule_date': schedule_date.isoformat(),
                    'json_data': schedule_result.schedule_data,
                    'time_slots': [process_time_slot(ts) for ts in time_slots]
                })
            else:
                return jsonify({'error': 'Schedule not found'}), 404
        else:
            all_schedules = ScheduleResult.query.filter(db.func.date(ScheduleResult.schedule_date) == schedule_date).all()
            grouped_schedules = {}
            for sr in all_schedules:
                elder = sr.elder
                time_slots = TimeSlot.query.filter_by(schedule_result_id=sr.id).order_by(TimeSlot.time_order).all()
                grouped_schedules[elder] = {
                    'schedule_date': sr.schedule_date.isoformat(),
                    'json_data': sr.schedule_data,
                    'time_slots': [process_time_slot(ts) for ts in time_slots]
                }
            return jsonify(grouped_schedules)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@main.route('/download_schedule/<string:elder>', methods=['GET'])
def download_schedule(elder):
    schedule_date_str = request.args.get('date', date.today().isoformat())
    schedule_date = datetime.strptime(schedule_date_str, "%Y-%m-%d").date()

    schedule_result = ScheduleResult.query.filter(
        ScheduleResult.elder == elder,
        func.date(ScheduleResult.schedule_date) == schedule_date
    ).first()

    if not schedule_result:
        abort(404, description="Schedule not found")

    time_slots = TimeSlot.query.filter_by(schedule_result_id=schedule_result.id).order_by(TimeSlot.time_order).all()

    df = pd.DataFrame([(ts.time_slot, ts.elder, ts.activity, ts.activity_id, 'lack' if ts.caregiver_id == '-1' else ts.caregiver, ts.caregiver_id, ts.schedule_date) for ts in time_slots],
                      columns=['TimeSlot', 'Elder', 'Activity', 'ActivityId', 'Caregiver', 'CaregiverId', 'ScheduleDate'])

    excel_buffer = io.BytesIO()
    df.to_excel(excel_buffer, index=False)
    excel_buffer.seek(0)

    return send_file(
        excel_buffer,
        mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        as_attachment=True,
        download_name=f'{elder}_schedule_{schedule_date.isoformat()}.xlsx'
    )

@main.route('/download_all_schedules', methods=['GET'])
def download_all_schedules():
    schedule_date_str = request.args.get('date', date.today().isoformat())
    schedule_date = datetime.strptime(schedule_date_str, "%Y-%m-%d").date()
    schedule_results = ScheduleResult.query.filter(db.func.date(ScheduleResult.schedule_date) == schedule_date).all()

    if not schedule_results:
        abort(404, description="No schedules found for the specified date")

    memory_file = io.BytesIO()
    with zipfile.ZipFile(memory_file, 'w') as zf:
        for schedule_result in schedule_results:
            time_slots = TimeSlot.query.filter_by(schedule_result_id=schedule_result.id).order_by(TimeSlot.time_order).all()
            df = pd.DataFrame([(ts.time_slot, ts.activity, 'lack' if ts.caregiver_id == '-1' else ts.caregiver) for ts in time_slots],
                              columns=['TimeSlot', 'Activity', 'Caregiver'])
            excel_buffer = io.BytesIO()
            df.to_excel(excel_buffer, index=False)
            excel_buffer.seek(0)
            zf.writestr(f"{schedule_result.elder}_schedule.xlsx", excel_buffer.getvalue())

    memory_file.seek(0)

    return send_file(
        memory_file,
        mimetype='application/zip',
        as_attachment=True,
        download_name=f'all_schedules_{schedule_date.isoformat()}.zip'
    )

@main.route('/nursing_actions', methods=['GET'])
def get_nursing_actions():
    actions = DicNursingAction.query.all()
    return jsonify([{
        'id': action.id,
        'pid': action.pid,
        'name': action.name,
        'level': action.level,
        'nursing_level': action.nursing_level
    } for action in actions])

@main.route('/elders', methods=['GET'])
def get_elders():
    elders = Elderdemand.query.filter_by(arrange='1').all()  # 只返回arrange为'1'的老人
    return jsonify([{
        'id': elder.id,
        'elder': elder.elder,
        'actions': elder.actions,
        'arrange': elder.arrange
    } for elder in elders])

@main.route('/caregivers', methods=['GET'])
def get_caregivers():
    caregivers = Attendantskills.query.all()
    return jsonify([{
        'id': caregiver.id,
        'attendant_name': caregiver.attendant_name,
        'skills': caregiver.skills
    } for caregiver in caregivers])

# 自动排班任务
def auto_schedule_task():
    """自动排班任务，每隔指定时间自动调用三班制排班接口"""
    from config_params import three_shift_params
    import time
    import logging
    import os
    from datetime import datetime, timedelta

    # 创建日志目录
    log_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'logs')
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)

    # 配置日志
    log_file = os.path.join(log_dir, three_shift_params.get('auto_schedule_log_file', 'auto_schedule.log'))
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        handlers=[
            logging.FileHandler(log_file),
            logging.StreamHandler()
        ]
    )
    logger = logging.getLogger("auto_schedule")

    # 获取自动排班的分钟数
    auto_schedule_minutes = three_shift_params.get('auto_schedule_minutes', 7)
    error_retry_minutes = three_shift_params.get('auto_schedule_error_retry_minutes', 1)
    days_ahead = three_shift_params.get('auto_schedule_days_ahead', 1)

    logger.info(f"自动排班任务启动，每 {auto_schedule_minutes} 分钟排班一次，提前 {days_ahead} 天生成排班")

    while True:
        try:
            # 生成目标日期（当前日期 + 提前天数）
            target_date = (datetime.now() + timedelta(days=days_ahead)).strftime("%Y-%m-%d")
            logger.info(f"开始自动排班，目标日期: {target_date}")

            # 调用三班制排班接口
            scheduler = ThreeShiftScheduler()
            result = scheduler.generate_and_save_schedule(
                # 使用全局参数，但覆盖开始日期
                start_date=target_date
            )

            # 检查排班结果
            if result.get('success'):
                logger.info(f"自动排班成功: {result}")
                logger.info(f"班次分配: {result.get('shift_assignments_count')} 个")
                logger.info(f"排班结果: {result.get('schedule_results_count')} 个")
                logger.info(f"时间段分配: {result.get('time_slots_count')} 个")
            else:
                logger.error(f"自动排班失败: {result}")

            # 等待指定时间
            logger.info(f"等待 {auto_schedule_minutes} 分钟后进行下一次排班")
            time.sleep(auto_schedule_minutes * 60)
        except Exception as e:
            logger.exception(f"自动排班出错: {str(e)}")
            # 出错后等待指定时间再试
            logger.info(f"等待 {error_retry_minutes} 分钟后重试")
            time.sleep(error_retry_minutes * 60)

# 启动自动排班任务
def start_auto_schedule():
    """启动自动排班任务"""
    from config_params import three_shift_params
    import threading
    import logging

    # 配置日志
    logger = logging.getLogger("auto_schedule_control")

    # 检查是否启用自动排班
    if three_shift_params.get('auto_schedule_enabled', False):
        # 创建并启动自动排班线程
        auto_thread = threading.Thread(target=auto_schedule_task)
        auto_thread.daemon = True  # 设置为守护线程，随主线程退出而退出
        auto_thread.start()
        logger.info(f"自动排班任务启动成功，每 {three_shift_params.get('auto_schedule_minutes', 7)} 分钟排班一次")
        print(f"[自动排班] 启动成功，每 {three_shift_params.get('auto_schedule_minutes', 7)} 分钟排班一次")
    else:
        logger.info("自动排班未启用，请在配置文件中设置 'auto_schedule_enabled' 为 True 来启用")
        print("[自动排班] 未启用，请在配置文件中设置 'auto_schedule_enabled' 为 True 来启用")

# 在应用启动时启动自动排班任务
start_auto_schedule()

# 自动排班控制API
@main.route('/auto_schedule/control', methods=['POST'])
def control_auto_schedule():
    """控制自动排班功能"""
    try:
        data = request.json or {}
        action = data.get('action')

        if action == 'start':
            # 启用自动排班
            from config_params import three_shift_params
            three_shift_params['auto_schedule_enabled'] = True

            # 启动自动排班任务
            start_auto_schedule()

            return jsonify({'success': True, 'message': '自动排班已启动'})
        elif action == 'stop':
            # 禁用自动排班
            from config_params import three_shift_params
            three_shift_params['auto_schedule_enabled'] = False

            # 注意：由于线程是守护线程，无法直接停止
            # 但设置 auto_schedule_enabled 为 False 后，下次应用重启时不会启动自动排班

            return jsonify({'success': True, 'message': '自动排班已禁用，将在应用重启后生效'})
        elif action == 'status':
            # 获取自动排班状态
            from config_params import three_shift_params

            return jsonify({
                'enabled': three_shift_params.get('auto_schedule_enabled', False),
                'minutes': three_shift_params.get('auto_schedule_minutes', 7),
                'days_ahead': three_shift_params.get('auto_schedule_days_ahead', 1),
                'generate_care_timeline': three_shift_params.get('auto_schedule_generate_care_timeline', True)
            })
        elif action == 'configure':
            # 配置自动排班参数
            from config_params import three_shift_params

            # 更新参数
            minutes = data.get('minutes')
            if minutes is not None:
                three_shift_params['auto_schedule_minutes'] = int(minutes)

            days_ahead = data.get('days_ahead')
            if days_ahead is not None:
                three_shift_params['auto_schedule_days_ahead'] = int(days_ahead)

            generate_care_timeline = data.get('generate_care_timeline')
            if generate_care_timeline is not None:
                three_shift_params['auto_schedule_generate_care_timeline'] = bool(generate_care_timeline)

            return jsonify({
                'success': True,
                'message': '自动排班参数已更新',
                'config': {
                    'minutes': three_shift_params.get('auto_schedule_minutes'),
                    'days_ahead': three_shift_params.get('auto_schedule_days_ahead'),
                    'generate_care_timeline': three_shift_params.get('auto_schedule_generate_care_timeline')
                }
            })
        else:
            return jsonify({'error': f'不支持的操作: {action}'}, 400)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

# 手动触发自动排班
@main.route('/auto_schedule/trigger', methods=['POST'])
def trigger_auto_schedule():
    """手动触发自动排班"""
    try:
        data = request.json or {}
        target_date = data.get('target_date')

        # 如果没有提供目标日期，使用当前日期 + 提前天数
        if not target_date:
            from config_params import three_shift_params
            from datetime import timedelta
            days_ahead = three_shift_params.get('auto_schedule_days_ahead', 1)
            target_date = (datetime.now() + timedelta(days=days_ahead)).strftime("%Y-%m-%d")

        # 调用三班制排班接口
        scheduler = ThreeShiftScheduler()
        result = scheduler.generate_and_save_schedule(
            # 使用全局参数，但覆盖开始日期
            start_date=target_date
        )

        return jsonify({
            'success': True,
            'message': f'成功触发自动排班，目标日期: {target_date}',
            'result': result
        })
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@main.route('/three_shift_schedule', methods=['POST'])
def generate_three_shift_schedule():
    """生成三班制排班计划API"""
    try:
        data = request.json or {}

        # 使用全局参数作为默认值
        from config_params import three_shift_params

        # 获取请求参数（如果提供，则覆盖全局参数）
        schedule_type = data.get('schedule_type', three_shift_params.get('schedule_type', 1))
        num_days = int(data.get('num_days', three_shift_params.get('num_days', 1)))
        start_date = data.get('start_date', three_shift_params.get('start_date'))
        shift_start_time = data.get('shift_start_time', three_shift_params.get('shift_start_time'))

        # 班制控制参数
        shift_mode = data.get('shift_mode')  # 班制模式
        custom_shifts = data.get('custom_shifts')  # 自定义班次
        enabled_shifts = data.get('enabled_shifts')  # 启用的班次
        disabled_shifts = data.get('disabled_shifts')  # 禁用的班次
        auto_adjust_time = data.get('auto_adjust_time')  # 是否自动调整班次时间

        # 休息时间控制参数
        min_rest_between_shifts = data.get('min_rest_between_shifts')  # 班次间最小休息时间
        min_rest_after_night_shift = data.get('min_rest_after_night_shift')  # 夜班后最小休息时间
        max_consecutive_shifts = data.get('max_consecutive_shifts')  # 最大连续工作班次数

        # 验证排班类型
        valid_schedule_types_str = ['daily', 'weekly', 'monthly', 'quarterly', 'yearly']
        valid_schedule_types_int = [1, 2, 3, 4, 5]

        # 如果是字符串类型
        if isinstance(schedule_type, str) and schedule_type not in valid_schedule_types_str:
            return jsonify({
                'error': f"不支持的排班类型: {schedule_type}。支持的类型: {', '.join(valid_schedule_types_str)}"
            }), 400
        # 如果是数字类型
        elif isinstance(schedule_type, int) and schedule_type not in valid_schedule_types_int:
            return jsonify({
                'error': f"不支持的排班类型数字: {schedule_type}。支持的类型: 1(按天), 2(按周), 3(按月), 4(按季度), 5(按年)"
            }), 400

        # 将数字类型转换为字符串类型（与原有代码兼容）
        schedule_type_map = {
            1: 'daily',
            2: 'weekly',
            3: 'monthly',
            4: 'quarterly',
            5: 'yearly'
        }

        # 如果是数字类型，转换为字符串
        if isinstance(schedule_type, int):
            schedule_type = schedule_type_map.get(schedule_type)

        # 验证天数参数（仅当排班类型为daily时需要）
        if schedule_type == 'daily' and (num_days < 1 or num_days > 365):
            return jsonify({'error': '天数参数必须在1到365之间'}), 400

        # 验证开始日期格式
        if start_date:
            try:
                datetime.strptime(start_date, "%Y-%m-%d")
            except ValueError:
                return jsonify({'error': '开始日期格式无效，请使用YYYY-MM-DD格式'}), 400

        # 验证班次开始时间格式
        if shift_start_time:
            try:
                datetime.strptime(shift_start_time, "%H:%M")
            except ValueError:
                return jsonify({'error': '班次开始时间格式无效，请使用HH:MM格式'}), 400

        # 实例化三班制排班调度器
        scheduler = ThreeShiftScheduler()

        # 如果提供了班制模式，设置班制模式
        if shift_mode:
            scheduler.set_shift_mode(
                mode=shift_mode,
                custom_shifts=custom_shifts,
                start_time=shift_start_time
            )

        # 如果提供了启用班次列表，更新班次配置
        if enabled_shifts:
            scheduler.update_shift_config(enabled_shifts=enabled_shifts)

        # 如果提供了禁用班次列表，设置禁用班次
        if disabled_shifts:
            scheduler.disable_shifts(disabled_shifts)

        # 如果提供了自动调整时间参数，更新班次控制参数
        if auto_adjust_time is not None:
            scheduler.update_shift_control(auto_adjust_time=auto_adjust_time)

        # 如果提供了休息时间控制参数，更新休息时间控制参数
        if min_rest_between_shifts is not None or min_rest_after_night_shift is not None or max_consecutive_shifts is not None:
            # 更新休息时间控制参数
            if min_rest_between_shifts is not None:
                scheduler.rest_time_control['min_rest_between_shifts'] = min_rest_between_shifts

            if min_rest_after_night_shift is not None:
                scheduler.rest_time_control['min_rest_after_night_shift'] = min_rest_after_night_shift

            if max_consecutive_shifts is not None:
                scheduler.rest_time_control['max_consecutive_shifts'] = max_consecutive_shifts

        # 生成并保存排班计划
        result = scheduler.generate_and_save_schedule(
            schedule_type=schedule_type,  # 已经在前面转换为字符串类型
            num_days=num_days,
            start_date=start_date,
            shift_start_time=shift_start_time
        )

        return jsonify(result)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@main.route('/three_shift_schedule', methods=['GET'])
def get_three_shift_schedule():
    """获取三班制排班计划API"""
    try:
        # 获取请求参数
        start_date_str = request.args.get('start_date')
        end_date_str = request.args.get('end_date')
        caregiver_id = request.args.get('caregiver_id')

        # 处理日期参数
        if start_date_str:
            try:
                start_date = datetime.strptime(start_date_str, "%Y-%m-%d").date()
            except ValueError:
                return jsonify({'error': '开始日期格式无效，请使用YYYY-MM-DD格式'}), 400
        else:
            # 默认为今天
            start_date = date.today()

        if end_date_str:
            try:
                end_date = datetime.strptime(end_date_str, "%Y-%m-%d").date()
            except ValueError:
                return jsonify({'error': '结束日期格式无效，请使用YYYY-MM-DD格式'}), 400
        else:
            # 默认为今天
            end_date = start_date

        # 验证日期范围
        if end_date < start_date:
            return jsonify({'error': '结束日期不能早于开始日期'}), 400

        # 查询排班数据
        if caregiver_id:
            # 查询特定护理员的排班，日期降序排序
            assignments = ShiftAssignment.get_assignments_by_caregiver(caregiver_id, start_date, end_date, date_desc=True)
        else:
            # 查询所有排班，日期降序排序
            assignments = ShiftAssignment.get_assignments_by_date_range(start_date, end_date, date_desc=True)

        # 构建响应数据
        result = {
            'start_date': start_date.isoformat(),
            'end_date': end_date.isoformat(),
            'total_assignments': len(assignments),
            'assignments': []
        }

        for assignment in assignments:
            result['assignments'].append({
                'id': assignment.id,
                'caregiver_id': assignment.caregiver_id,
                'caregiver_name': assignment.caregiver_name,
                'shift_date': assignment.shift_date.isoformat(),
                'shift_type': assignment.shift_type,
                'shift_start_time': assignment.shift_start_time.strftime("%H:%M"),
                'shift_end_time': assignment.shift_end_time.strftime("%H:%M"),
                'schedule_type': assignment.schedule_type
            })

        return jsonify(result)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@main.route('/elder_schedule/<string:elder_id>', methods=['GET'])
def get_elder_schedule(elder_id):
    """获取老人的详细排班信息"""
    try:
        # 获取请求参数
        date_str = request.args.get('date', date.today().isoformat())

        # 处理日期参数
        try:
            schedule_date = datetime.strptime(date_str, "%Y-%m-%d").date()
        except ValueError:
            return jsonify({'error': '日期格式无效，请使用YYYY-MM-DD格式'}), 400

        # 查询老人的排班结果
        schedule_result = ScheduleResult.query.filter_by(
            elder=elder_id,
            schedule_date=schedule_date
        ).first()

        if not schedule_result:
            return jsonify({'error': f'未找到老人 {elder_id} 在 {date_str} 的排班信息'}), 404

        # 查询时间段安排
        time_slots = TimeSlot.query.filter_by(
            schedule_result_id=schedule_result.id
        ).order_by(TimeSlot.time_order).all()

        # 构建响应数据
        result = {
            'elder_id': elder_id,
            'schedule_date': schedule_date.isoformat(),
            'schedule_data': schedule_result.schedule_data,
            'time_slots': []
        }

        for slot in time_slots:
            result['time_slots'].append({
                'time_slot': slot.time_slot,
                'activity': slot.activity,
                'activity_id': slot.activity_id,
                'caregiver': slot.caregiver,
                'caregiver_id': slot.caregiver_id,
                'time_order': slot.time_order
            })

        return jsonify(result)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@main.route('/download_three_shift_schedule', methods=['GET'])
def download_three_shift_schedule():
    """下载三班制排班计划"""
    try:
        # 获取请求参数
        start_date_str = request.args.get('start_date')
        end_date_str = request.args.get('end_date')

        # 处理日期参数
        if start_date_str:
            try:
                start_date = datetime.strptime(start_date_str, "%Y-%m-%d").date()
            except ValueError:
                return jsonify({'error': '开始日期格式无效，请使用YYYY-MM-DD格式'}), 400
        else:
            # 默认为今天
            start_date = date.today()

        if end_date_str:
            try:
                end_date = datetime.strptime(end_date_str, "%Y-%m-%d").date()
            except ValueError:
                return jsonify({'error': '结束日期格式无效，请使用YYYY-MM-DD格式'}), 400
        else:
            # 默认为今天
            end_date = start_date

        # 验证日期范围
        if end_date < start_date:
            return jsonify({'error': '结束日期不能早于开始日期'}), 400

        # 查询排班数据
        assignments = ShiftAssignment.get_assignments_by_date_range(start_date, end_date)

        if not assignments:
            return jsonify({'error': '指定日期范围内没有排班数据'}), 404

        # 创建DataFrame
        data = []
        for a in assignments:
            data.append({
                '护理员ID': a.caregiver_id,
                '护理员姓名': a.caregiver_name,
                '排班日期': a.shift_date.isoformat(),
                '班次类型': a.shift_type,
                '开始时间': a.shift_start_time.strftime("%H:%M"),
                '结束时间': a.shift_end_time.strftime("%H:%M"),
                '排班类型': a.schedule_type
            })

        df = pd.DataFrame(data)

        # 生成Excel文件
        excel_buffer = io.BytesIO()
        df.to_excel(excel_buffer, index=False)
        excel_buffer.seek(0)

        return send_file(
            excel_buffer,
            mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            as_attachment=True,
            download_name=f'three_shift_schedule_{start_date.isoformat()}_to_{end_date.isoformat()}.xlsx'
        )
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@main.errorhandler(404)
def not_found(error):
    return make_response(jsonify({'error': str(error)}), 404)

def init_app(app):
    app.register_blueprint(main)

    # 通过POST请求到 /generate_and_save_schedule  生成新的调度并保存到数据库。
    # 通过GET请求到 /view_schedule查看保存的调度。
    # 通过GET请求到 /download_all_schedules或 /download_schedule/<elder_id> 下载保存的调度。

    # 照护计划id
    # 老人id
    # 时间段
    # 护理动作
    # 护理员
    # 更新时间
